package org.cainiao.io.netty.other.transport;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * PlainNioServer<br />
 * <p>
 * Author: Cai Niao(wdhlzd@163.com)<br />
 */
public class PlainNioServer {

    public void serve(int port) {
        try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(port));
            Selector selector = Selector.open();
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes());
            for (; ; ) {
                try {
                    selector.select();
                } catch (IOException ex) {
                    ex.printStackTrace();
                    // handle exception
                    break;
                }
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    if (key.isAcceptable()) {
                        SocketChannel client = ((ServerSocketChannel) key.channel()).accept();
                        client.configureBlocking(false);
                        client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate());
                        System.out.println("Accepted connection from " + client);
                    } else if (key.isReadable() || key.isWritable()) {
                        try (SocketChannel client = (SocketChannel) key.channel()) {
                            if (key.isReadable()) {
                                // TODO 读入数据，立即读立即写是否有问题，待验证
                            }
                            if (key.isWritable()) {
                                ByteBuffer buffer = (ByteBuffer) key.attachment();
                                while (buffer.hasRemaining()) {
                                    if (client.write(buffer) == 0) {
                                        break;
                                    }
                                }
                            }
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}
